# src/main.py
# 轻量级区块链配置溯源系统（完整可运行版）

from flask import Flask, request, jsonify, render_template
import os
import datetime
import jwt
import matplotlib
matplotlib.use('Agg')  # 无 GUI 环境必备
import matplotlib.pyplot as plt
import csv

# -------------------- JWT 工具 --------------------
SECRET = os.getenv("JWT_SECRET", "dev-secret-change-in-production")

def create_token(user_id: str, role: str = "user") -> str:
    payload = {
        "sub": user_id,
        "role": role,
        "exp": datetime.datetime.utcnow() + datetime.timedelta(hours=2),
        "iat": datetime.datetime.utcnow()
    }
    return jwt.encode(payload, SECRET, algorithm="HS256")

def decode_token(token: str):
    try:
        return jwt.decode(token, SECRET, algorithms=["HS256"])
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None

def require_auth(f):
    from functools import wraps
    @wraps(f)
    def decorated(*args, **kwargs):
        auth_header = request.headers.get("Authorization")
        if not auth_header or not auth_header.startswith("Bearer "):
            return jsonify({"error": "缺少 Authorization 头或格式错误"}), 401
        token = auth_header.split(" ")[1]
        payload = decode_token(token)
        if not payload:
            return jsonify({"error": "无效或过期的令牌"}), 401
        request.user = payload
        return f(*args, **kwargs)
    return decorated

# -------------------- Flask 初始化 --------------------
app = Flask(__name__,
            template_folder="frontend/templates",
            static_folder="frontend/static")

# -------------------- 内存演示存储 --------------------
demo_storage = []

# -------------------- 路由 --------------------
@app.route("/")
def index():
    return render_template("index.html")

@app.route("/generate-token")
def generate_token_route():
    token = create_token(user_id="admin", role="operator")
    return jsonify({"token": token})

@app.route("/upload-config", methods=["POST"])
@require_auth
def upload_config():
    data = request.get_json()
    config = data.get("config")
    device_id = data.get("device_id", "Unknown")
    operator = data.get("operator", "admin")
    if not config:
        return jsonify({"error": "配置内容不能为空"}), 400

    block_hash = f"0x{os.urandom(16).hex()}"
    return jsonify({
        "status": "success",
        "block": {
            "hash": block_hash,
            "index": 1,
            "device_id": device_id,
            "operator": operator
        }
    })

# ****** 已修复：返回字段完整 ******
@app.route("/api/add-config", methods=["POST"])
def api_add_config():
    data = request.get_json()
    config = data.get("config", "")
    device_id = data.get("device_id", "Router1")
    operator = data.get("operator", "admin")

    if not config.strip():
        return jsonify({"error": "请输入配置内容"}), 400

    full_size = len(config.encode('utf-8'))
    diff_size = sum(len(line.encode('utf-8')) for line in config.strip().splitlines())
    added_lines = [line.rstrip() for line in config.strip().splitlines()[-3:] if line.strip()]

    result = {
        "index": len(demo_storage) + 1,
        "full": full_size,
        "diff": diff_size,
        "added_lines": added_lines
    }
    demo_storage.append(result)
    return jsonify(result)

@app.route("/api/generate-chart", methods=["POST"])
def api_generate_chart():
    data = request.get_json()
    results = data.get("results", [])
    if not results:
        return jsonify({"error": "无数据可生成图表"}), 400

    versions = [f"V{i+1}" for i in range(len(results))]
    full_sizes = [r["full"] for r in results]
    diff_sizes = [r["diff"] for r in results]

    os.makedirs("src/frontend/static/docs", exist_ok=True)
    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")

    plt.figure(figsize=(10, 6))
    plt.plot(versions, full_sizes, label="全量配置大小 (B)", marker='o')
    plt.plot(versions, diff_sizes, label="差异大小 (B)", marker='s')
    plt.title("配置版本存储对比分析")
    plt.xlabel("版本")
    plt.ylabel("大小 (字节)")
    plt.legend()
    plt.grid(True, alpha=0.3)
    png_path = f"src/frontend/static/docs/chart_{timestamp}.png"
    plt.savefig(png_path)
    plt.close()

    csv_path = f"src/frontend/static/docs/chart_{timestamp}.csv"
    with open(csv_path, "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        writer.writerow(["版本", "全量大小(B)", "差异大小(B)"])
        for i, r in enumerate(results):
            writer.writerow([f"V{i+1}", r["full"], r["diff"]])

    return jsonify({
        "png_url": f"/static/docs/chart_{timestamp}.png",
        "csv_url": f"/static/docs/chart_{timestamp}.csv"
    })

@app.route("/chain_latest")
@require_auth
def chain_latest():
    chain = [
        {
            "index": 1,
            "hash": "0xabc123def456...",
            "timestamp": datetime.datetime.now().timestamp(),
            "data": {
                "device_id": "Router1",
                "operator": "admin",
                "diff": "interface eth0\n ip address 192.168.1.1"
            }
        },
        {
            "index": 2,
            "hash": "0xdef456ghi789...",
            "timestamp": datetime.datetime.now().timestamp() - 3600,
            "data": {
                "device_id": "Router1",
                "operator": "admin",
                "diff": "router ospf 1\n network 192.168.1.0 0.0.0.255 area 0"
            }
        }
    ]
    return jsonify(chain)

# -------------------- 启动 --------------------
if __name__ == "__main__":
    print("服务启动中... 访问 http://localhost:5000")
    app.run(host="0.0.0.0", port=5000, debug=True)